scrabble-solver
Version:
Scrabble Solver 2 - Free, open-source, cross-platform, multi-language analysis tool for Scrabble, Scrabble Duel, Super Scrabble, Letter League, Crossplay, Literaki, and Kelimelik. Quickly find the top-scoring words using the given board and tiles.
75 lines (60 loc) • 2.18 kB
text/typescript
import { games } from '@scrabble-solver/configs';
import { COMMA_ARABIC, COMMA_LATIN } from '@scrabble-solver/constants';
import { dictionaries } from '@scrabble-solver/dictionaries';
import { logger } from '@scrabble-solver/logger';
import { type Locale, isLocale } from '@scrabble-solver/types';
import { getWordDefinition } from '@scrabble-solver/word-definitions';
import { type NextApiRequest, type NextApiResponse } from 'next';
import { getServerLoggingData } from '@/api';
interface RequestData {
locale: Locale;
words: string[];
}
const MAXIMUM_COLLISIONS_COUNT = Object.values(games).reduce((result, game) => Math.max(result, game.rackSize), 0);
const MAXIMUM_WORDS_COUNT = MAXIMUM_COLLISIONS_COUNT + 1;
const dictionary = async (request: NextApiRequest, response: NextApiResponse): Promise<void> => {
const meta = getServerLoggingData(request);
try {
const { locale, words } = parseRequest(request);
logger.info('dictionary - request', {
meta,
payload: {
locale,
words,
},
});
const trie = await dictionaries.get(locale);
const results = await Promise.all(words.map((word) => getWordDefinition(locale, word, trie.has(word))));
response.status(200).send(results.map((result) => result.toJson()));
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';
logger.error('dictionary - error', { error, meta });
response.status(500).send({ error: 'Server error', message });
}
};
const parseRequest = (request: NextApiRequest): RequestData => {
const { locale, word } = request.query;
if (!isLocale(locale)) {
throw new Error('Invalid "locale" parameter');
}
if (typeof word !== 'string' || word.length === 0) {
throw new Error('Invalid "word" parameter');
}
const words = Array.from(
new Set(
word
.replaceAll(COMMA_ARABIC, COMMA_LATIN)
.split(COMMA_LATIN)
.map((part) => part.trim())
.filter(Boolean),
),
);
if (words.length > MAXIMUM_WORDS_COUNT) {
throw new Error('Invalid "word" parameter');
}
return {
locale,
words,
};
};
export default dictionary;